home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xpat2-1.000 / xpat2-1 / xpat2-1.04 / src / Xaw-main.c < prev    next >
C/C++ Source or Header  |  1995-11-25  |  15KB  |  444 lines

  1. /*****************************************************************************/
  2. /*                                         */
  3. /*                                         */
  4. /*    X patience version 2 -- module Xaw-main.c                 */
  5. /*                                         */
  6. /*    main function for the Athena Widget interface                 */
  7. /*    written by Michael Bischoff (mbi@mo.math.nat.tu-bs.de)             */
  8. /*    March-1994                                 */
  9. /*    see COPYRIGHT.xpat2 for Copyright details                 */
  10. /*                                         */
  11. /*                                         */
  12. /*****************************************************************************/
  13. #ifdef useXaw
  14. #include "X-pat.h"
  15. #include "Tableau.h"
  16. #include "version.h"
  17.  
  18. Window table, mainwindow;
  19. Widget toplevel;
  20.  
  21. static void perform_command(Widget widget, XtPointer client_data, XtPointer call_data) {
  22.     (*(void (*)(void))client_data)();    /* any questions? */
  23. }
  24.  
  25. void create_help(void);
  26. void popup_help(void);
  27. void popdown_help(Widget, XtPointer, XtPointer);
  28.  
  29. static Widget messagebox, container, desktop;
  30.  
  31. void show_message(const char *str, ...) {
  32.     static char last_message[256];
  33.     Arg Args;
  34.     va_list args;
  35.     va_start(args, str);
  36.  
  37.     if (!str) {
  38.     memset(last_message, ' ', sizeof(last_message)-1);
  39.     last_message[sizeof(last_message)-1] = '\0';
  40.     } else
  41.     vsprintf(last_message, str, args);
  42.  
  43.     XtSetArg(Args, XtNlabel, last_message);
  44.     XtSetValues(messagebox, &Args, 1);
  45. }
  46.  
  47.  
  48.  
  49. static XtAppContext app_con;
  50. static void (*execfunc)(void) = NULL;
  51. static Widget dialog, popup;
  52.  
  53. void cmd_LeavePat(void) {
  54.     play_sound("goodbye");
  55.     XtDestroyApplicationContext(app_con);
  56.     exit(0);
  57. }
  58.  
  59. static void popup_confirm(const char *prompt) {
  60.     Arg args[2];
  61.     Position x, y;
  62.     Dimension xx, yy;
  63.  
  64.     XtSetArg(args[0], XtNlabel, prompt);
  65.     XtSetValues(dialog, args, 1);
  66.     XtVaGetValues(dialog, XtNwidth, &xx, XtNheight, &yy, NULL);
  67.     x = (graphic.w_width/2) - xx/2;
  68.     y = (graphic.w_height/3) - yy/2;
  69.  
  70.     XtTranslateCoords(toplevel, x, y, &x, &y);
  71.     XtSetArg(args[0], XtNx, x);
  72.     XtSetArg(args[1], XtNy, y);
  73.     XtSetValues(popup, args, 2);
  74.     XtPopup(popup, XtGrabNone);
  75. }
  76.  
  77. void cmd_Confirm(void) {
  78.     if (execfunc) {
  79.     void (*execfunc2)(void) = execfunc;    /* erase it first! */
  80.     execfunc = NULL;
  81.     XtPopdown(popup);
  82.     (*execfunc2)();    /* finally execute the desired function */
  83.     }
  84. }
  85. void cmd_Cancel(void) {
  86.     if (execfunc) {
  87.     execfunc = NULL;
  88.     XtPopdown(popup);
  89.     }
  90. }
  91.  
  92. /* type converter functions: */
  93. static void mXtAP_Cancel (Widget w, XEvent *xev, String *params, Cardinal *num) { cmd_Cancel();  }
  94. static void mXtAP_Confirm(Widget w, XEvent *xev, String *params, Cardinal *num) { cmd_Confirm(); }
  95. static void Cancel(Widget widget, XtPointer client_data, XtPointer call_data)    { cmd_Cancel();  }
  96. static void Ok(Widget widget, XtPointer client_data, XtPointer call_data)    { cmd_Confirm(); }
  97.  
  98. void request_confirm(void (*dofunc)(void), const char *prompt) {
  99.     if (execfunc)
  100.     return;        /* request pending => deny another one */
  101.     execfunc = dofunc;
  102.     popup_confirm(prompt);
  103. }
  104.  
  105. static String fallback_resources[] = { 
  106.     "*beNiceToColormap:            false",
  107.     "*shapeStyle:            Rectangle",
  108.     "*topShadowContrast:        20",
  109.     "*bottomShadowContrast:        40",
  110.     "*Scrollbar*background:        Grey70",
  111.     "*Background:            grey85",
  112.     "*Foreground:            black",
  113.     "*resizeToPreferred:        True",
  114.     "*input:                True",
  115.     "*showGrip:                off",
  116.     "*shadowWidth:                       2",
  117.     "*messages.justify:            Left",
  118.     "*upperbox.orientation:        XtorientHorizontal",
  119.     "*lowerbox.orientation:        XtorientHorizontal",
  120.     "*Tableau.backingStore:        WhenMapped",
  121.     "*Tableau.keyboardFile:        keys",
  122.     "*Tableau.messageFile:        messages",
  123.     "*Tableau.background:        LightSlateGray",
  124.     "*Tableau.arrowColor:        Gold",
  125.     "*Tableau.markColor:        Black",
  126.     "*Tableau.rules:                Gypsy",
  127.     "*Tableau.rng:                1",
  128.     "*Viewport.allowHoriz:        True",
  129.     "*Viewport.allowVert:        True",
  130.     "*Viewport.useBottom:        True",
  131.     "*Viewport.useRight:        True",
  132.     "*Label.shadowWidth:        0",
  133.     "*Label.BorderWidth:        2",
  134.     "*Dialog*Translations: #override \n<Key>y: Ok()\n<Key>n: Cancel()\n",
  135.     "XPat*title:            XPat",
  136.     "XPat.prompt.allowShellResize:    True",
  137.     "XPat.prompt.saveUnder:        True",
  138.     "*Dialog*resizable:            True",
  139.     "*Hint.Translations: #override\n<BtnDown>:set()\n<BtnUp>:HintNotify()unset()\n",
  140.     "*Sound.state:            True",
  141.     "XPat.help.width:            403",
  142.     "XPat.help.height:            200",
  143.     "XPat.help.title:            XPat Help Window",
  144.     "XPat.help.saveUnder:        True",
  145.     "XPat*Close Help.fromHoriz:        Topic",
  146.     "*helptext*string:            Please choose a topic.",
  147.     "*helptext*displayCaret:        False",
  148.     "*helptext*scrollHorizontal:    whenNeeded",
  149.     "*helptext*scrollVertical:        whenNeeded",
  150.     "*helptext*editType:        read",
  151.     NULL,
  152. };
  153.  
  154. static XrmOptionDescRec options[] = {
  155.     /* tableau resources */
  156.     { "-xpmdir",    "*Tableau.xpmdir",    XrmoptionSepArg, NULL },
  157.     { "-rules",        "*Tableau.rules",    XrmoptionSepArg, NULL },
  158.     { "-faceup",    "*Tableau.faceup",    XrmoptionSepArg, NULL },
  159.     { "-facedown",    "*Tableau.facedown",    XrmoptionSepArg, NULL },
  160.     { "-decks",        "*Tableau.decks",    XrmoptionSepArg, NULL },
  161.     { "-slots",     "*Tableau.slots",    XrmoptionSepArg, NULL },
  162.     { "-jokers",    "*Tableau.jokers",    XrmoptionSepArg, NULL },
  163.     { "-tmps",        "*Tableau.tmps",    XrmoptionSepArg, NULL },
  164.     { "-relaxed",       "*Tableau.relaxed",    XrmoptionSepArg, NULL },
  165.     { "-flips",            "*Tableau.flips",    XrmoptionSepArg, NULL },
  166.     { "-turn",        "*Tableau.turn",    XrmoptionSepArg, NULL },
  167.     { "-rotations",    "*Tableau.rotations",    XrmoptionSepArg, NULL },
  168.     { "-rng",        "*Tableau.rng",        XrmoptionSepArg, NULL },
  169. #ifdef GFX1
  170. #ifdef LOADCARDS
  171.     { "-cards",        "*Tableau.cardset",    XrmoptionSepArg, NULL },
  172. #endif
  173.     { "-cb",            "*Tableau.cardbackColor",XrmoptionSepArg,NULL },
  174.     { "-red",            "*Tableau.RedColor",    XrmoptionSepArg, NULL },
  175. #endif
  176.     { "-tb",            "*Tableau.background",    XrmoptionSepArg,NULL },
  177.     { "-arrowcolor",    "*Tableau.arrowColor",    XrmoptionSepArg, NULL },
  178.     { "-markcolor",    "*Tableau.markColor",    XrmoptionSepArg, NULL },
  179.     { "-markwidth",    "*Tableau.markWidth",    XrmoptionSepArg, NULL },
  180.  
  181.     /* non-tableau resources */
  182. #ifdef SOUND
  183.     { "-sound",     "*Sound.state",          XrmoptionNoArg, (XtPointer)"True" },
  184.     { "-nosound",     "*Sound.state",          XrmoptionNoArg, (XtPointer)"False" },
  185. #endif
  186. };
  187.  
  188. static void HintNotify(Widget w, XEvent *xev, String *params, Cardinal *num) {
  189.     /* check to be sure state is still Set so that user can cancel
  190.        the action (e.g. by moving outside the window, in the default
  191.        bindings. */
  192.     /* Nope, we cannot do this, the 'set' state is private data */
  193.     /* CommandWidget cbw = (CommandWidget)w; 
  194.     if (cbw->command.set)
  195.     XtCallCallbackList(w, cbw->command.callbacks, (XtPointer) NULL); */
  196.     switch (((XButtonPressedEvent *)xev)->button) {
  197.     case Button1:
  198.     cmd_NextHint();
  199.     break;
  200.     case Button2:
  201.     cmd_DoHint();
  202.     break;
  203.     case Button3:
  204.     cmd_PreviousHint();
  205.     }
  206. }
  207.  
  208.  
  209. static XtActionsRec moreActions[] = {
  210.     { "HintNotify",    HintNotify },
  211.     { "Cancel",        mXtAP_Cancel },
  212.     { "Ok",        mXtAP_Confirm }
  213. };
  214.  
  215. static void reportfunc(Widget wid, XtPointer client_data, XtPointer call_data) {
  216.     XawPannerReport *rep;
  217.     if (game.graphic)
  218.     cmd_ResetHints();
  219.     rep = (XawPannerReport *)call_data;
  220.     if (graphic.w_width != rep->slider_width || graphic.w_height != rep->slider_height) {
  221.     static int busy = 0;    /* hope this fixes cycling */
  222.     /* size was changed */
  223.     if (busy)
  224.         ;/*printf("doing nothing, I\'m busy!\n"); */
  225.     else {
  226.         graphic.w_width = rep->slider_width;
  227.         graphic.w_height = rep->slider_height;
  228.         if (game.graphic) {
  229.         int w, h;
  230.         busy = 1;
  231.         init_layout();
  232.         w = max(graphic.preferred_width, graphic.w_width);
  233.         h = max(graphic.preferred_height, graphic.w_height);
  234.         AskWidgetForResize(w, h);
  235.         busy = 0;
  236.         }
  237.     }
  238.     }
  239. }
  240.  
  241. char *loadfilename;
  242.  
  243. static void process_extra_args(int argc, char *argv[]) {
  244.     /* check extra args */
  245.     game.seed = -1L;
  246.     loadfilename = NULL;
  247.     if (argc > 2) {
  248.     usage:
  249.     fprintf(stderr, "xpat: invalid argument: %s\n", argv[1]);
  250.     fprintf(stderr, "usage: xpat2 [options] [seed|loadfilename]\n"
  251.         "options are all standard X11 toolkit options and\n"
  252.         "-xpmdir (dir)       to set directory for xpm files\n"
  253.                 "-rules (ruleset)    to initially use specified rules\n"
  254.         "-faceup|facedown|decks|slots|jokers|tmps (num) customize parameters\n"
  255.         "-relaxed|flips|turn|rotations (num)            customize parameters\n"
  256.         "-tb (color)         set background color of tableau\n"
  257.         "-arrowcolor (color) set color of hint arrow\n"
  258.         "-markcolor (color)  set color of frame to mark cards\n"
  259.         "-markwidth (wdth)   set width of frame to mark cards\n"
  260. #ifdef SOUND
  261.         "-sound              sound toggle on\n"
  262.         "-nosound            sound toggle off\n"
  263. #endif
  264. #ifdef GFX1
  265. #ifdef LOADCARDS
  266.         "-cards (filename)   to load external bitmap cardset\n"
  267. #endif
  268.         "-cb (color)         set cardback color\n"
  269.         "-red (color)        use a different 'red' for static grey screens\n"
  270. #endif
  271.         );
  272.     exit(EXIT_FAILURE);
  273.     } else if (argc == 2) {
  274.     /* seed or load file */
  275.     if (*argv[1] == '-')
  276.         goto usage;
  277.     else if (isdigit(*argv[1])) {
  278.         game.seed = atol(argv[1]);
  279.         if (game.seed < 0L || game.seed >= 1000000000L)
  280.         goto usage;
  281.     } else {
  282.         loadfilename = argv[1];
  283.         /* printf("loadfile is %s\n", loadfilename); */
  284.     }
  285.     }
  286.     /* printf("in process_args: seed is %ld\n", game.seed); */
  287. }
  288.  
  289. /*extern void cmd_DebugOut(void); */
  290. extern struct rules *rulepool[];
  291. static void selectrules(Widget w, XtPointer number, XtPointer garbage) {
  292.     const char *s = XtName(w);
  293.     /* printf("widget %s has been selected\n", s); */
  294.     change_rules(s);
  295. }
  296.  
  297. #ifdef SOUND
  298. static Widget sound;
  299.  
  300. int checksound(void) {
  301.     Boolean retval;
  302.     Arg args[1];
  303.     XtSetArg(args[0], XtNstate, &retval);
  304.     XtGetValues(sound, args, 1);
  305.     return retval & 0xff;
  306. }
  307. #endif
  308.  
  309. static Widget paned;
  310.  
  311. int main(int argc, char *argv[]) {
  312.     Widget buttonpanel;
  313.     Widget gamebutton, gamemenu, rulesbutton, rulesmenu;
  314.     int i;
  315.     struct button {
  316.     const char *name; void (*func)(void);
  317.     } *bp;
  318.     static struct button buttons[] = {
  319.     { "Cards",          cmd_DealCards },
  320.     { "Undo",          cmd_UndoMove },
  321.     { "Redo",          cmd_RedoMove },
  322.     { "Score",          cmd_ShowScore },
  323.     { "Hint",          cmd_NextHint },
  324.     { "Move to Stack",    cmd_ToStack },
  325.     /* { "Debug",        cmd_DebugOut }, */
  326. #ifdef ONLINE_HELP
  327.     { "Help",          popup_help },
  328. #endif
  329.     { "Save",          cmd_SaveGame }
  330.     }, mbuttons[] = {
  331.     { "Drop Bookmark",    cmd_DropBookmark },
  332.     { "Goto Bookmark",    cmd_GotoBookmark },
  333.     { "Replay",        cmd_ReplayGame },
  334.     { "Restart",        cmd_RestartGame },
  335.     { "New Game",        rq_AnotherGame },
  336.     { "Quit",        rq_LeavePat }
  337.     };
  338.  
  339.     /* use the command line arguments concerning the widgets */
  340.     switch_uid(1);    /* switch to real uid for reading .Xauthority */
  341.     toplevel = XtAppInitialize(&app_con, "XPat", options, XtNumber(options),
  342.                    &argc, argv, fallback_resources, NULL, 0);
  343.     switch_uid(0);    /* back to effective uid */
  344.     process_extra_args(argc, argv);
  345.     XtAppAddActions(app_con, moreActions, XtNumber(moreActions));
  346.     graphics_control(Disable);
  347.  
  348.     /* basic elements */
  349.     paned       = XtCreateManagedWidget("paned",    panedWidgetClass,    toplevel,      NULL, 0);
  350.     buttonpanel = XtCreateManagedWidget("buttonpanel",    boxWidgetClass,     paned,      NULL, 0);
  351.     messagebox = XtCreateManagedWidget("messages", labelWidgetClass, paned, NULL, 0);
  352.     show_message(" ");
  353.  
  354.     container   = XtCreateManagedWidget("container",    viewportWidgetClass, paned,      NULL, 0);
  355.     desktop     = XtCreateManagedWidget("desktop",    tableauWidgetClass,  container,      NULL, 0);
  356.     XtAddCallback(container, XtNreportCallback, reportfunc, NULL);
  357.  
  358.     /* create the button panel and its menus */
  359.     gamebutton  = XtCreateManagedWidget("Game", menuButtonWidgetClass, buttonpanel, NULL, 0);
  360.     gamemenu    = XtCreatePopupShell("gamemenu", simpleMenuWidgetClass, gamebutton, NULL, 0);
  361.     for (bp = mbuttons, i = 0; i < XtNumber(mbuttons); ++i) {
  362.     Widget w;
  363.     w = XtCreateManagedWidget(bp->name, smeBSBObjectClass, gamemenu, NULL, 0);
  364.     if (bp->func) XtAddCallback(w, XtNcallback, perform_command, bp->func);
  365.     ++bp;
  366.     }
  367.     XtVaSetValues(gamebutton, XtNmenuName, "gamemenu", NULL);
  368.  
  369.     /* create Rules button just right of the Game button */
  370.     rulesbutton = XtCreateManagedWidget("Rules", menuButtonWidgetClass, buttonpanel, NULL, 0);
  371.     rulesmenu   = XtCreatePopupShell("rulesmenu", simpleMenuWidgetClass, rulesbutton, NULL, 0);
  372.     {   struct rules **rp;
  373.     for (rp = rulepool; *rp; ++rp) {
  374.         Widget w;
  375.         w = XtCreateManagedWidget((*rp)->shortname, smeBSBObjectClass, rulesmenu, NULL, 0);
  376.         XtAddCallback(w, XtNcallback, selectrules, NULL);
  377.     }
  378.     }
  379.     XtVaSetValues(rulesbutton, XtNmenuName, "rulesmenu", NULL);
  380.  
  381.     /* rest of the buttons */
  382.     for (bp = buttons, i = 0; i < XtNumber(buttons); ++i) {
  383.     Widget w;
  384.     w = XtCreateManagedWidget(bp->name, commandWidgetClass, buttonpanel, NULL, 0);
  385.     if (bp->func) XtAddCallback(w, XtNcallback, perform_command, bp->func);
  386.     ++bp;
  387.     }
  388. #ifdef SOUND
  389.     sound = XtCreateManagedWidget("Sound", toggleWidgetClass, buttonpanel, NULL, 0);
  390. #endif
  391.  
  392.     /* OK. Now do the pop-up shells */
  393.     popup = XtCreatePopupShell("prompt", transientShellWidgetClass, toplevel, NULL, 0);
  394.     dialog = XtCreateManagedWidget("dialog", dialogWidgetClass, popup, NULL, 0);
  395.     XawDialogAddButton(dialog, "ok",     Ok,     (XtPointer)dialog);
  396.     XawDialogAddButton(dialog, "cancel", Cancel, (XtPointer)dialog);
  397.  
  398. #ifdef ONLINE_HELP
  399.     create_help();
  400. #endif
  401.     graphic.w_width = graphic.w_height = 0;
  402.     XtRealizeWidget(toplevel);
  403.     mainwindow = XtWindow(toplevel);
  404.     table  = XtWindow(desktop);
  405.     XtRealizeWidget(popup);
  406.  
  407.     graphics_control(Enable);
  408.     init_layout();            /* position the piles in a nice way */
  409.     for (i = 0; i < game.numpiles; ++i)
  410.     pile_resize(i);
  411.     show_message(TXT_WELCOME, VERSION);
  412.     XStoreName(dpy, mainwindow, rules.longname ? rules.longname : rules.shortname);
  413.     if (!graphic.w_width) {
  414.     graphic.w_width = graphic.width;
  415.     graphic.w_height = graphic.height;
  416.     }
  417.     /* printf("before mainloop: seed is %ld\n", game.seed); */
  418.     XtAppMainLoop(app_con);    /* does not return */
  419.     return 0;            /* keep compiler happy */
  420. }
  421.  
  422. void Force_Resize(XSize_t w, XSize_t h) {
  423.     /* for Xlib, we can use this size. It does include space for buttons and messagebox */
  424. #ifdef useXaw
  425.     /* for Xaw, we have to add the size of the buttonbox and the message window */
  426.     /* note that the result may have a wrong height, due to recalculation of the box
  427.        widget. A second call to this function will always give the correct result. */
  428.     /* The overall size can be computed by adding the difference between the current
  429.        size of the mainwindow - current size of viewport window */
  430.     {   Arg args[1];
  431.         int hh;
  432.     Dimension hhh = 0;
  433.         XtSetArg(args[0], XtNheight, &hhh);
  434.         XtGetValues(paned, args, 1);
  435.     hh = hhh;        /* unsigned short => int */
  436.         h += hh - graphic.w_height;    /* difference between overall size and Viewport size */
  437.     /* sanity check! */
  438.     }
  439. #endif    
  440.     XResizeWindow(dpy, mainwindow, w, h);
  441.     /* or should XSetWMSizeHints() be used? */
  442. }
  443. #endif
  444.